home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
music
/
eked-m1.zoo
/
src
/
gm
/
key_man.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-19
|
5KB
|
183 lines
/*
* EKED-M1 : Editor for Korg M1 synth; key_man.c : keyboard equivalents
* Copyright (C) 1995 Steven M. Eker (Steven.Eker@brunel.ac.uk)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stddef.h>
#include <string.h>
#include <ctype.h>
#include <osbind.h>
#include <gemfast.h>
#include "gem_man.h"
/*
* shift_code = 00000000 0000ACLR (alt, ctrl, left, right)
* scan_code = 00000000 0sssssss
* lookup code = 000000ss sssssACS where S = L|R
*/
#define KE_CODE(s, r) (((s) >> 1) | ((s) & 1) | ((r) << 3))
#define KE_HASH(c) (((unsigned) (c)) % MAX_EQUIV)
typedef struct {
char *name; /* Key name as it appears in menu */
char code; /* scancode */
} NAMED_KEY;
static KEY_EQUIV ke_table[MAX_EQUIV];
static void check_for_equiv(int title, int item, char *string);
static int ascii2key(char c);
KEY_EQUIV *km_get_equiv(int shift_code, int scan_code)
{
int c = KE_CODE(shift_code, scan_code);
KEY_EQUIV *start = ke_table + KE_HASH(c), *k = start;
do{
if(k->code == c)
return k;
if(k->code == 0) /* most key combinations won't be equivalents! */
break;
if(++k == ke_table + MAX_EQUIV)
k = ke_table;
}while(k != start);
return NULL;
}
void km_set_equiv(int shift_code, int scan_code, int title, int item)
{
int c = KE_CODE(shift_code, scan_code);
KEY_EQUIV *start = ke_table + KE_HASH(c), *k = start;
do{
if(k->code == c || k->code == 0){
k->code = c;
k->title = title;
k->item = item;
return;
}
if(++k == ke_table + MAX_EQUIV)
k = ke_table;
}while(k != start);
}
void km_scan_menu(OBJECT *menu)
{
int active = menu[menu[0].ob_head].ob_head, dropdown = menu[0].ob_tail;
int t, b, i;
for(t = menu[menu[active].ob_head].ob_next,
b = menu[menu[dropdown].ob_head].ob_next;
t != active && b != dropdown; t = menu[t].ob_next, b = menu[b].ob_next){
for(i = menu[b].ob_head; i != b; i = menu[i].ob_next)
check_for_equiv(t, i, (char *) menu[i].ob_spec);
}
}
static void check_for_equiv(int title, int item, char *string)
{
static NAMED_KEY misc[] = {
{"Tab", 0x0F}, {"Esc", 0x01}, {"ClrHome", 0x47}, {"Del", 0x53},
{"Undo", 0x61}, {"Bksp", 0x0E}, {"Help", 0x62}, {"Enter", 0x72},
{"Ins", 0x52}, {"Ret", 0x1C}, {NULL, 0x00}
};
int i, c, n, start, end, seeking_space, shift_code, scan_code;
size_t l;
NAMED_KEY *p;
n = 0;
seeking_space = 0;
for(i = 0; string[i]; i++){
if(isspace(string[i])){
if(seeking_space){
end = i - 1;
seeking_space = 0;
}
}
else{
if(!seeking_space){
n++;
start = i;
seeking_space = 1;
}
}
}
if(n < 2)
return;
if(seeking_space)
end = i - 1;
/*
* More than two words; last word is string[start]...string[end]
* Check for modifiers
*/
shift_code = 0;
for(i = start; i < end; i++){
c = string[i];
if(c == 0x01)
shift_code |= 1; /* shift */
else if(c == '^')
shift_code |= 4; /* control */
else if(c == 0x07)
shift_code |= 8; /* alternate */
else
break;
}
/*
* Check for a valid key name
*/
scan_code = -1;
if(i == end) /* one character - assume ASCII */
scan_code = ascii2key(string[i]);
else if(string[i] == 'F' && isdigit(string[i + 1]) && i + 2 <= end){
n = string[i + 1] - '0';
if(i + 2 == end)
n = isdigit(string[i + 2]) ? 10 * n + string[i + 2] - '0' : 0;
if(n >= 1){
if(n <= 10)
scan_code = (0x3B - 1) + n;
else if(n <= 20)
scan_code = (0x54 - 11) + n;
}
}
else{
for(p = misc; p->code; p++){
l = strlen(p->name);
if(end - i + 1 == l && strncmp(string + i, p->name, l) == 0){
scan_code = p->code;
break;
}
}
}
if(scan_code > 0)
km_set_equiv(shift_code, scan_code, title, item);
}
static int ascii2key(char c)
{
_KEYTAB *p = Keytbl((char *) -1, (char *) -1, (char *) -1);
char *unshift = p->unshift, *shift = p->shift, *caps = p->caps;
int i;
for(i = 0; i <= 127; i++){
if(unshift[i] == c || shift[i] == c || caps[i] == c)
return i;
}
return -1;
}